const WebSocket = require('ws');
const http = require('http');
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const os = require('os');

// 配置
const config = {
  port: process.env.PORT || 3000,
  roomPassword: process.env.ROOM_PASSWORD || '', // 房间密码，为空则不需要密码
  maxFileSize: 1024 * 1024 * 100, // 最大文件大小限制：100MB
  heartbeatInterval: 30000, // 心跳间隔：30秒
  heartbeatTimeout: 60000, // 心跳超时：60秒
};

// 获取本机IP地址
function getLocalIPs() {
  const interfaces = os.networkInterfaces();
  const addresses = [];
  
  for (const name of Object.keys(interfaces)) {
    for (const interface of interfaces[name]) {
      // 跳过内部IP和非IPv4地址
      if (interface.internal || interface.family !== 'IPv4') continue;
      addresses.push(interface.address);
    }
  }
  
  return addresses;
}

// 创建HTTP服务器
const server = http.createServer((req, res) => {
  // 处理favicon.ico请求
  if (req.url === '/favicon.ico') {
    res.writeHead(404);
    res.end();
    return;
  }

  // 移除URL中的查询参数
  const urlPath = req.url.split('?')[0];
  const filePath = urlPath === '/' ? '/index.html' : urlPath;
  const fullPath = path.join(__dirname, filePath.replace(/^\//, ''));
  
  // 安全检查：防止目录遍历
  if (!fullPath.startsWith(__dirname)) {
    res.writeHead(403);
    res.end('Forbidden');
    return;
  }

  // 检查文件是否存在
  if (!fs.existsSync(fullPath)) {
    res.writeHead(404);
    res.end('404 Not Found');
    return;
  }
  
  // 检查是否是文件
  const stat = fs.statSync(fullPath);
  if (!stat.isFile()) {
    res.writeHead(403);
    res.end('Forbidden');
    return;
  }

  fs.readFile(fullPath, (err, data) => {
    if (err) {
      console.error('Error reading file:', err);
      res.writeHead(500);
      res.end('Internal Server Error');
      return;
    }

    const ext = path.extname(filePath);
    const contentType = {
      '.html': 'text/html; charset=utf-8',
      '.js': 'text/javascript; charset=utf-8',
      '.css': 'text/css; charset=utf-8',
      '.json': 'application/json; charset=utf-8',
      '.png': 'image/png',
      '.jpg': 'image/jpeg',
      '.gif': 'image/gif',
      '.svg': 'image/svg+xml',
      '.ico': 'image/x-icon'
    }[ext] || 'text/plain; charset=utf-8';

    // 添加安全相关的响应头
    const headers = {
      'Content-Type': contentType,
      'X-Content-Type-Options': 'nosniff',
      'X-Frame-Options': 'SAMEORIGIN',
      'X-XSS-Protection': '1; mode=block',
      'Cache-Control': 'no-cache, no-store, must-revalidate',
      'Pragma': 'no-cache',
      'Expires': '0'
    };

    res.writeHead(200, headers);
    res.end(data);
  });
});

// 创建WebSocket服务器
const wss = new WebSocket.Server({ server });

// 用户管理
const users = new Map();
const fileTransfers = new Map();

// 清理无效的文件传输
function cleanupFileTransfers() {
  const now = Date.now();
  for (const [fileId, transfer] of fileTransfers.entries()) {
    if (now - transfer.timestamp > config.heartbeatTimeout) {
      fileTransfers.delete(fileId);
    }
  }
}

// 广播消息给所有用户
function broadcast(message, exclude = null) {
  const data = JSON.stringify(message);
  wss.clients.forEach(client => {
    if (client !== exclude && client.readyState === WebSocket.OPEN) {
      client.send(data);
    }
  });
}

// 发送消息给特定用户
function sendTo(userId, message) {
  const user = users.get(userId);
  if (user && user.ws.readyState === WebSocket.OPEN) {
    user.ws.send(JSON.stringify(message));
  }
}

// 心跳检测
function heartbeat() {
  wss.clients.forEach(ws => {
    if (ws.isAlive === false) {
      return ws.terminate();
    }
    
    ws.isAlive = false;
    ws.ping();
  });
}

// WebSocket连接处理
wss.on('connection', (ws, req) => {
  let currentUser = null;
  
  // 设置心跳检测
  ws.isAlive = true;
  ws.on('pong', () => {
    ws.isAlive = true;
  });

  // 获取客户端IP
  const ip = req.headers['x-forwarded-for']?.split(',')[0].trim() || 
             req.socket.remoteAddress;

  // 检查房间密码
  if (config.roomPassword) {
    ws.send(JSON.stringify({ type: 'room_password_required' }));
    ws.isAuthenticated = false;
  } else {
    ws.isAuthenticated = true;
  }

  ws.on('message', (message) => {
    try {
      const data = JSON.parse(message);

      // 如果需要密码且未认证，只处理密码验证消息
      if (config.roomPassword && !ws.isAuthenticated) {
        if (data.type === 'room_password') {
          if (data.password === config.roomPassword) {
            ws.isAuthenticated = true;
            ws.send(JSON.stringify({ 
              type: 'room_password_result',
              success: true 
            }));
          } else {
            ws.send(JSON.stringify({ 
              type: 'room_password_result',
              success: false 
            }));
          }
        }
        return;
      }

      switch (data.type) {
        case 'join':
          currentUser = {
            userId: data.userId,
            nickname: data.nickname,
            ip,
            ws,
            joinTime: Date.now()
          };
          users.set(data.userId, currentUser);
          
          // 发送当前用户列表
          ws.send(JSON.stringify({
            type: 'users',
            users: Array.from(users.entries()).map(([id, user]) => [
              id,
              {
                userId: user.userId,
                nickname: user.nickname,
                joinTime: user.joinTime
              }
            ])
          }));

          // 广播新用户加入
          broadcast({
            type: 'join',
            userId: data.userId,
            nickname: data.nickname,
            joinTime: currentUser.joinTime
          }, ws);
          break;

        case 'message':
          if (!currentUser) return;
          
          if (data.toUserId) {
            // 私聊消息
            sendTo(data.toUserId, {
              type: 'message',
              content: data.content,
              userId: currentUser.userId,
              timestamp: Date.now(),
              isPrivate: true
            });
            // 发送给自己
            ws.send(JSON.stringify({
              type: 'message',
              content: data.content,
              userId: currentUser.userId,
              timestamp: Date.now(),
              isPrivate: true,
              toUserId: data.toUserId
            }));
          } else {
            // 群发消息
            broadcast({
              type: 'message',
              content: data.content,
              userId: currentUser.userId,
              timestamp: Date.now()
            });
          }
          break;

        case 'nickname':
          if (currentUser) {
            currentUser.nickname = data.nickname;
            broadcast({
              type: 'nickname',
              userId: currentUser.userId,
              nickname: data.nickname
            });
          }
          break;

        case 'file_offer':
          if (currentUser) {
            const fileId = data.fileId;
            fileTransfers.set(fileId, {
              from: currentUser.userId,
              to: data.toUserId,
              fileName: data.fileName,
              fileSize: data.fileSize,
              chunks: [],
              timestamp: Date.now()
            });
            sendTo(data.toUserId, {
              type: 'file_offer',
              fileId,
              fileName: data.fileName,
              fileSize: data.fileSize,
              fromUserId: currentUser.userId
            });
          }
          break;

        case 'file_chunk':
          const transfer = fileTransfers.get(data.fileId);
          if (transfer) {
            transfer.chunks.push(data.chunk);
            transfer.timestamp = Date.now();
            sendTo(transfer.to, {
              type: 'file_chunk',
              fileId: data.fileId,
              chunk: data.chunk
            });
          }
          break;

        case 'file_complete':
          const completedTransfer = fileTransfers.get(data.fileId);
          if (completedTransfer) {
            sendTo(completedTransfer.to, {
              type: 'file_complete',
              fileId: data.fileId
            });
            fileTransfers.delete(data.fileId);
          }
          break;
      }
    } catch (error) {
      console.error('Error handling message:', error);
    }
  });

  ws.on('close', () => {
    if (currentUser) {
      users.delete(currentUser.userId);
      broadcast({
        type: 'leave',
        userId: currentUser.userId,
        timestamp: Date.now()
      });
    }
  });

  ws.on('error', (error) => {
    console.error('WebSocket error:', error);
    ws.terminate();
  });
});

// 启动心跳检测
const heartbeatInterval = setInterval(heartbeat, config.heartbeatInterval);
const cleanupInterval = setInterval(cleanupFileTransfers, config.heartbeatInterval);

// 清理定时器
wss.on('close', () => {
  clearInterval(heartbeatInterval);
  clearInterval(cleanupInterval);
});

// 启动服务器
server.listen(config.port, () => {
  const ips = getLocalIPs();
  console.log('\n=== 局域网聊天服务器已启动 ===');
  console.log(`本地访问：http://localhost:${config.port}`);
  console.log('局域网访问：');
  ips.forEach(ip => {
    console.log(`http://${ip}:${config.port}`);
  });
  if (config.roomPassword) {
    console.log('\n房间密码：', config.roomPassword);
  }
  console.log('\n按 Ctrl+C 停止服务器');
}); 